#!/usr/bin/python3
import sys
sys.path.append('/home/oect')
import codecs
import csv
import os
import re
import shutil
import json
import subprocess
from typing import Iterable
from src.config import constant
from src.libs.logger import logger
from src.libs.executecmd import ExecuteCmd
from src.libs.base import set_repo
from src.libs.base import  replase


class Command:
    """
    dnf/osc相关命令的执行
    """
    def __init__(self, package, path=None) -> None:
        self.package = package
        self._save_path = path
        if not os.path.exists(self._save_path):
            os.makedirs(self._save_path, exist_ok=True)
        
    def download(self):
        """dnf下载源码包"""
        cmd_result = subprocess.run(
            args=["dnf", "download", self.package, "--source"],
            shell=False,
            cwd=self._save_path,
        )
        return cmd_result.returncode == 0

    def _unrpm(self, del_source=True):
        cmd_result = subprocess.run(
            args=["unrpm", self.package + "*.src.rpm"], shell=False, cwd=self._save_path
        )
        if del_source and cmd_result.returncode == 0:
            os.system(
                "rm -rf %s" % os.path.join(self._save_path, self.package + "*.src.rpm")
            )
        return os.listdir(self._save_path)

    def _osc_project(self, project, project_path, clean=True, package=None):
        if clean:
            content = '<project name="%s"></project>' % project
        else:
            content = """
                    <project name="{project}">
                        <package name="{package}" state="A" />
                    </project>
            """.format(
                project=project, package=package
            )
        if not os.path.exists(project_path + "/.osc/_packages"):
            raise FileNotFoundError("project dictory not found ")
        with open(project_path + "/.osc/_packages", "w", encoding="utf-8") as file:
            file.write(content)

    def _osc_remove(self, project_path, file):
        cwd = os.path.join(project_path, file)
        subprocess.run(args=["osc", "addremove"], shell=False, cwd=cwd)
        subprocess.run(args=["osc", "ci", "-n"], shell=False, cwd=cwd)


    def pull_obs_project(self, project, path):
        """拉取特定的工程"""
        cmd_result = subprocess.run(args=["osc", "co", project], shell=False, cwd=path)
        return cmd_result.returncode == 0

    @classmethod
    def provides_source(cls, provide):
        """
        获取组件对应的源码包
        """
        dnf_query_bin = ["dnf", "repoquery", "--whatprovides", provide]
        binary_package = ExecuteCmd.cmd_output(dnf_query_bin)

        if not binary_package:
            return None

        binary_package = binary_package.split("\n")[0]
        source_package = cls.binary_source(binary_package)

        return provide, source_package

    @classmethod
    def binary_source(cls, binary_package):
        """
        获取二进制对应的源码包名
        """
        source_package = 'NA'
        # binary_package = 'python3-cherrypy'
        # dnf_query_src = ["dnf", "repoquery", "--source", binary_package]
        dnf_query_src = f"dnf repoquery --source {binary_package}"
        cmd_ouput = ExecuteCmd.cmd_output(dnf_query_src.split())
        if  cmd_ouput is None:
            logger.error(f"{dnf_query_src} failed")
            return source_package
        
        data = cmd_ouput.split("\n")

        for line in data:
            if 'src.rpm' in line:
                source_package = line
                break

        logger.info(source_package)
        return source_package
        

    @staticmethod
    def wget(folder, url):
        """
        通过wget下载
        """
        os.system("wget -P %s -nc %s" % (folder, url))
    
    @classmethod
    def get_rpms_2_compare(cls, pkg):
        """
        @description :Get the list of packages to compare
        -----------
        @param : pkg
        -----------
        @returns :
        -----------
        """
        query_rpm_requires = "rpm -pq --requires --nosignature {pkgpath}/{rpm}"
        query_rpm_provides = "rpm -pq --provides --nosignature {pkgpath}/{rpm}"
        old_rpm_path = "/home/21.09-bin"
        new_rpm_path = "/home/22.03-bin"
        ls_new_cmd = f"ls {new_rpm_path}"
        ls_new_out = ExecuteCmd.cmd_output(ls_new_cmd.split())
        if  ls_new_out is None:
            logger.warning("No new rpms")
            return True
        new_data = ls_new_out.split("\n")
        new_rpms = []
        for line in new_data:
            if '.rpm' in line and '.src.rpm' not in line:
                new_rpms.append(line)
        
        logger.info(new_rpms)

        for rpm in new_rpms:
            query_new_rpm_requires = query_rpm_requires.format(pkgpath = new_rpm_path, rpm = rpm)
            query_old_rpm_requires = query_rpm_requires.format(pkgpath = old_rpm_path, rpm = rpm)
            query_new_rpm_provides = query_rpm_provides.format(pkgpath = new_rpm_path, rpm = rpm)
            query_old_rpm_provides = query_rpm_provides.format(pkgpath = old_rpm_path, rpm = rpm)

            query_new_requires_out = ExecuteCmd.cmd_output(query_new_rpm_requires.split())
            query_old_requires_out = ExecuteCmd.cmd_output(query_old_rpm_requires.split())
            query_new_provides_out = ExecuteCmd.cmd_output(query_new_rpm_provides.split())
            query_old_provides_out = ExecuteCmd.cmd_output(query_old_rpm_provides.split())

            if  query_new_requires_out is None or query_old_requires_out is None or \
                query_new_provides_out is None or query_old_provides_out is None:
                logger.error(f" query {rpm} requires/provides failed")
                return False
            
            new_requires_data = query_new_requires_out.split("\n")
            old_requires_data = query_old_requires_out.split("\n")
            requires_difference = set(new_requires_data).symmetric_difference(set(old_requires_data))

            new_provides_data = query_new_provides_out.split("\n")
            old_provides_data = query_old_provides_out.split("\n")
            provides_difference = set(new_provides_data).symmetric_difference(set(old_provides_data))

            if  requires_difference is None and provides_difference is None:
                continue
            elif requires_difference is not None:
                logger.info(f"requires of {rpm} different :[{requires_difference}]")
                return False
            else:
                logger.info(f"provides of {rpm} different :[{provides_difference}]")
                return False

        logger.info(f"Both of requires/provides of {pkg} rpms are same!")
        return True


# if __name__ == "__main__":
#     # binary_file = '/root/home:Admin:ISO/openEuler-22.03-LTS-Next/unable_install_list_aarch64'
#     binary_file = '/home/oect/baseos'
#     bin_srcs = dict()
#     set_repo('oe_repo_file')
#     with open(binary_file, 'r', encoding='utf-8') as bins:
#         for bin in bins.readlines():
#             bin = bin.strip()
#             src = Command.binary_source(bin)
#             logger.info(f"src:{src}")
#             src = replase(src)
#             bin_srcs[bin] = src
#             logger.info(f"bin: {bin}; src:{src}")

#     # check_dep_log = '/home/oect/consoleText.txt'
#     # with open(check_dep_log, 'r', encoding='utf-8') as logs:
        

#     with codecs.open('check_dependence.csv', 'w', 'utf-8') as result_file:
#             writer = csv.writer(result_file)
#             writer.writerow(["binary", "source"])

#             for bin, src in bin_srcs.items():
#                 bin_src = [bin, src]
#                 logger.info(f"{bin_src}")
#                 writer.writerow(bin_src)